<!--
 * @Description: webRTC界面
 * @Date: 2024-02-19 14:29:24
 * @FilePath: \demod:\12electron\electron-demo\src\renderer\src\views\webRTC\index.vue
-->
<template>
  <div class="webRTC-container">
    <div class="video-container">
      <div class="video-box">
        <video id="local" ref="localVideo" autoplay playsinline muted></video>
        <div class="video-title">我</div>
      </div>
      <div class="video-box">
        <video id="remote" ref="remoteVideo" autoplay playsinline></video>
        <div class="video-title">远程视频</div>
      </div>
    </div>

    <div class="operation">
      <!-- step1 -->
      <div class="step">
        <div class="user">用户 1 的操作区域</div>
        <p class="desc">
          点击 Create Offer，生成 SDP offer，把下面生成的offer 复制给用户 2
          <el-button id="create-offer" type="primary" @click="createOffer">创建 Offer</el-button>
        </p>

        <p>SDP offer:</p>
        <el-input v-model="offerSdp">
          <template #append>
            <el-button type="success" @click="copyToClipboard(offerSdp, 'offer')">点击复制</el-button>
          </template>
        </el-input>
      </div>

      <!-- step2 -->
      <div class="step">
        <div class="user">用户 2 的操作区域</div>
        <p>用户 2将用户1 刚才生成的SDP offer 粘贴到下方，点击 "创建答案 "来生成SDP答案，然后将 SDP Answer 复制给用户 1。</p>

        <el-input v-model="offerSdp2">
          <template #append>
            <el-button type="success" size="default" @click="createAnswer">创建 Answer</el-button>
          </template>
        </el-input>

        <p>SDP Answer:</p>
        <el-input v-model="answerSdp">
          <template #append>
            <el-button type="success" size="default" @click="copyToClipboard(answerSdp, 'answer')">点击复制</el-button>
          </template>
        </el-input>
      </div>

      <!-- step3 -->
      <div class="step">
        <div class="user">用户 1 的操作区域</div>

        <p>将用户 2 创建的 Answer 粘贴到下方，然后点击 Add Answer。</p>

        <p>SDP Answer:</p>
        <el-input v-model="answerSdp2">
          <template #append>
            <el-button type="success" size="default" @click="addAnswer">Add Answer</el-button>
          </template>
        </el-input>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup name="webRTC">
import { downloadStrToTextFile } from '@renderer/utils/transData';
import { onMounted, ref } from 'vue';
import 'webrtc-adapter'; // 你只需要引入它即可，不需要做任何配置和多余的操作

const localVideo = ref(); // 本地视频
const remoteVideo = ref(); // 远程视频

// 内网中使用
const peerConnection = new RTCPeerConnection(); // 创建一个 RTCPeerConnection对象，用于后面实现本地计算机到远端的 WebRTC 连接

// 创建本地/远程 SDP(绘画描述协议) 描述, 用于描述本地/远程的媒体流
const offerSdp = ref('');
const answerSdp = ref(''); // 远端返回的答案

onMounted(() => {
  init();
});

// 复制内容到剪贴板
const copyToClipboard = (val: string, name: string = '') => {
  navigator.clipboard.writeText(val);

  downloadStrToTextFile(val, name);
};

// 初始化采集本地视频流
const init = async () => {
  // 获取本地端视频标签
  // const localVideo = document.getElementById('local') as HTMLVideoElement
  // 获取远程端视频标签
  // const remoteVideo = document.getElementById('remote') as HTMLVideoElement

  // 采集本地媒体流,包含音频与视频
  const localStream = await navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true,
  });
  // 设置本地视频流
  localVideo.value.srcObject = localStream;

  // 添加本地媒体流的轨道都添加到 RTCPeerConnection 中
  localStream.getTracks().forEach((track) => {
    peerConnection.addTrack(track, localStream);
  });

  // 监听远程流，方法一：
  peerConnection.ontrack = (event) => {
    remoteVideo.value.srcObject = event.streams[0];
  };

  // 方法二：你也可以使用 addStream API，来更加详细的控制流的添加
  // const remoteStream: MediaStream = new MediaStream()
  // peerConnection.ontrack = (event) => {
  //   event.streams[0].getTracks().forEach((track) => {
  //     remoteStream.addTrack(track)
  //   })
  //   // 设置远程视频流
  //   remoteVideo.srcObject = remoteStream
  // }
};

// 创建 offer
const createOffer = async () => {
  debugger;
  // 创建本地的SDP描述
  const offer = await peerConnection.createOffer();
  // 设置本地SDP描述
  await peerConnection.setLocalDescription(offer);
  // 到这里，我们本地的 offer 就创建好了，一般在这里通过信令服务器发送 offerSdp 给远端
  console.log(peerConnection); // 存放有外网ip

  // 监听 RTCPeerConnection 的 onicecandidate 事件，当 ICE 服务器返回一个新的候选地址时，就会触发该事件
  peerConnection.onicecandidate = async (event) => {
    if (event.candidate) {
      offerSdp.value = JSON.stringify(peerConnection.localDescription);
    }
  };
};

// 创建 answer
const offerSdp2 = ref(''); // 存放对方发送来的sdp
const createAnswer = async () => {
  debugger;
  // 解析对方发送来的sdp字符串
  const offer = JSON.parse(offerSdp2.value);
  // 监听 RTCPeerConnection 的 onicecandidate 事件，当 ICE 服务器返回一个新的候选地址时，就会触发该事件
  peerConnection.onicecandidate = async (event) => {
    if (event.candidate) {
      answerSdp.value = JSON.stringify(peerConnection.localDescription);
    }
  };
  await peerConnection.setRemoteDescription(offer);
  const answer = await peerConnection.createAnswer();
  await peerConnection.setLocalDescription(answer);
};

// 添加 answer(应答)
const answerSdp2 = ref('');
const addAnswer = async () => {
  const answer = JSON.parse(answerSdp2.value);
  if (!peerConnection.currentRemoteDescription) {
    peerConnection.setRemoteDescription(answer);
  }
};
</script>

<style lang="scss" scoped>
.webRTC-container {
  height: 90%;
  padding: 10px;
  font-size: 20px;
  color: #fff;
  overflow-y: scroll;

  user-select: text;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;

  .video-container {
    max-width: 500px;
    display: grid;
    grid-template-rows: 1fr 1fr;
    grid-template-columns: 1fr;
    gap: 1em;
    width: 100%;
    padding: 10px;

    .video-box {
      position: relative;

      .video-title {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        background-color: rgb(0 0 0 / 50%);
        color: #fff;
        text-align: center;
        padding: 5px 0;
      }
    }

    video {
      width: 100%;
      height: 100%;
      border: 4px solid #048ff2;
      background-color: #516fa3;
      border-radius: 30px;
    }
  }

  .operation {
    width: 520px;

    .step {
      padding: 30px;
      background-color: #516fa3;
      margin: 10px 0;
      color: white;
      border-radius: 20px;

      .user {
        width: 200px;
        text-align: center;

        // font-size: 18px;
        padding: 10px;
        font-weight: bold;
        background: #36495d;
        border-radius: 20px;
      }

      .desc {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin: 10px 0;
        gap: 20px;
      }
    }
  }
}
</style>
